
#ifndef __MATHLIB_H__
#define __MATHLIB_H__


typedef float				vec_t;
typedef float				vec2_t[2];
typedef float				vec3_t[3];
typedef float				vec4_t[4];
typedef float				vec5_t[5];

extern vec3_t vec3_origin;

#define DotProduct(x,y)			((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
#define CrossProduct(x,y,o)		((o)[0]=(x)[1]*(y)[2]-(x)[2]*(y)[1],(o)[1]=(x)[2]*(y)[0]-(x)[0]*(y)[2],(o)[2]=(x)[0]*(y)[1]-(x)[1]*(y)[0])
#define VectorCopy(i,o)			((o)[0]=(i)[0],(o)[1]=(i)[1],(o)[2]=(i)[2])
#define VectorSet(v,x,y,z)		((v)[0]=(x),(v)[1]=(y),(v)[2]=(z))
#define VectorClear(v)			((v)[0]=(v)[1]=(v)[2]=0)
#define VectorCompare(a,b)		((a)[0]==(b)[0]&&(a)[1]==(b)[1]&&(a)[2]==(b)[2])
#define VectorAdd(a,b,o)		((o)[0]=(a)[0]+(b)[0],(o)[1]=(a)[1]+(b)[1],(o)[2]=(a)[2]+(b)[2])
#define VectorSubtract(a,b,o)	((o)[0]=(a)[0]-(b)[0],(o)[1]=(a)[1]-(b)[1],(o)[2]=(a)[2]-(b)[2])
#define	VectorScale(v,s,o)		((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
#define VectorMultiply(a,b,o)	((o)[0]=(a)[0]*(b)[0],(o)[1]=(a)[1]*(b)[1],(o)[2]=(a)[2]*(b)[2])
#define	VectorMA(a,s,b,o)		((o)[0]=(a)[0]+(b)[0]*(s),(o)[1]=(a)[1]+(b)[1]*(s),(o)[2]=(a)[2]+(b)[2]*(s))
#define VectorNegate(v,o)		((o)[0]=-(v)[0],(o)[1]=-(v)[1],(o)[2]=-(v)[2])
#define VectorInverse(v)		((v)[0]=-(v)[0],(v)[1]=-(v)[1],(v)[2]=-(v)[2])
#define VectorLength(v)			(sqrt((v)[0]*(v)[0]+(v)[1]*(v)[1]+(v)[2]*(v)[2]))

__inline float VectorNormalize (vec3_t v){

	float	length, invLength;

	length = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);

	if (length){
		invLength = 1.0 / length;

		v[0] *= invLength;
		v[1] *= invLength;
		v[2] *= invLength;
	}
	
	return length;
}

__inline float VectorNormalize2 (vec3_t v, vec3_t out){

	float	length, invLength;

	length = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);

	if (length){
		invLength = 1.0 / length;

		out[0] = v[0] * invLength;
		out[1] = v[1] * invLength;
		out[2] = v[2] * invLength;
	}
	else
		out[0] = out[1] = out[2] = 0.0;
	
	return length;
}

__inline void ClearBounds (vec3_t mins, vec3_t maxs){

	mins[0] = mins[1] = mins[2] = 999999;
	maxs[0] = maxs[1] = maxs[2] = -999999;
}

__inline void AddPointToBounds (const vec3_t point, vec3_t mins, vec3_t maxs){

	if (point[0] < mins[0])
		mins[0] = point[0];
	if (point[0] > maxs[0])
		maxs[0] = point[0];

	if (point[1] < mins[1])
		mins[1] = point[1];
	if (point[1] > maxs[1])
		maxs[1] = point[1];

	if (point[2] < mins[2])
		mins[2] = point[2];
	if (point[2] > maxs[2])
		maxs[2] = point[2];
}

__inline float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ) {
	int		i;
	vec3_t	corner;
	float	a, b;

	for (i=0 ; i<3 ; i++) {
		a = fabs( mins[i] );
		b = fabs( maxs[i] );
		corner[i] = a > b ? a : b;
	}

	return VectorLength (corner);
}


#endif	// __MATHLIB_H__
